package redis

import (
	"context"
	"fmt"
	"time"

	"github.com/go-redis/redis/v8"

	"mxshop-api/user-web/global"
)

var rdb *redis.Client

type ExistsErr struct{}

func (e ExistsErr) Error() string {
	return fmt.Sprint("key is exists")
}

func NewExistsErr() error {
	return ExistsErr{}
}

func Init() (err error) {
	rdb = redis.NewClient(&redis.Options{
		Addr:     fmt.Sprintf("%s:%d", global.ServerConfig.RedisConfig.Host, global.ServerConfig.RedisConfig.Port),
		Password: global.ServerConfig.RedisConfig.Password, // no password set
		DB:       global.ServerConfig.RedisConfig.DB,       // use default DB
		PoolSize: global.ServerConfig.RedisConfig.PoolSize, // 连接池大小
	})

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	_, err = rdb.Ping(ctx).Result()
	return err
}

// GetSet check whether key exists and if exists return ExistsErr.
// If it does not exist the value is set.
func GetSet(ctx context.Context, key string, value interface{}, expiration time.Duration) (err error) {
	_, err = rdb.Get(ctx, key).Result()
	if err == nil {
		return NewExistsErr()
	}
	if err != redis.Nil {
		return err
	}
	err = rdb.Set(ctx, key, value, expiration).Err()
	if err != nil {
		return err
	}
	return nil
}

// CheckDelSMSCode check that the sms code is correct.
// delete the key if it is correct.
func CheckDelSMSCode(ctx context.Context, key, code string) (ok bool, err error) {
	val, err := rdb.Get(ctx, key).Result()
	if err != nil {
		if err == redis.Nil {
			return false, nil
		}
		return false, err
	}
	if val != code {
		return false, nil
	}

	err = rdb.Del(ctx, key).Err()
	if err != nil {
		return false, err
	}
	return true, nil
}
